package org.chen.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.chen.common.exception.ExceptionCodeEnum;
import org.chen.common.exception.FlyingException;
import org.chen.common.model.travel.StoreTravelOrder;
import org.chen.common.request.PageParamRequest;
import org.chen.mapper.StoreTravelOrderMapper;
import org.chen.service.StoreTravelOrderService;
import org.chen.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class StoreTravelOrderServiceImpl extends ServiceImpl<StoreTravelOrderMapper, StoreTravelOrder> implements StoreTravelOrderService {

    @Autowired
    private StoreTravelOrderMapper travelOrderMapper;

    @Autowired
    private OrderUtils orderUtils;

    @Autowired
    private UserService userService;

    @Override
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public StoreTravelOrder getByPayIdWithLock(String payId) {
        return baseMapper.selectOne(new QueryWrapper<StoreTravelOrder>()
                .eq("pay_id", payId)
                .last("FOR UPDATE"));
    }

    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public StoreTravelOrder getByOrderIdWithLock(String orderId) {
        return baseMapper.selectOne(new QueryWrapper<StoreTravelOrder>()
                .eq("order_id", orderId)
                .last("FOR UPDATE"));
    }

    @Transactional(isolation = Isolation.REPEATABLE_READ)
    @Override
    public StoreTravelOrder getByOrderNoWithLock(String orderNo) {
        return baseMapper.selectOne(new QueryWrapper<StoreTravelOrder>()
                .eq("order_id", orderNo)
                .last("FOR UPDATE"));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateOrderStatus(Long id, Integer oldStatus, Integer newStatus) {
        return baseMapper.update(null, new UpdateWrapper<StoreTravelOrder>()
                .eq("id", id)
                .eq("status", oldStatus)
                .set("status", newStatus));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateOrder(Long id, Integer version) {
        return baseMapper.update(null, new UpdateWrapper<StoreTravelOrder>()
                .eq("id", id)
                .eq("version", version)
                .set("version", version + 1)
                .set("is_del", true)
                .set("is_system_del", true)
                .set("status", 3));
    }

    /**
     * 根据订单号查询订单信息
     * @param id 订单id
     * @return 计算后的价格集合
     */
    public StoreTravelOrder getInfoById(Long id) {
        StoreTravelOrder storeOrder = travelOrderMapper.selectById(id);
        Integer userId = userService.getUserIdException();

        if(null == storeOrder || !userId.equals(storeOrder.getUid())){
            //订单号错误
            throw new FlyingException(ExceptionCodeEnum.NO_RELEVANT_ORDER_INFORMATION_FOUND,"没有找到相关订单信息!");
        }

        return storeOrder;
    }

    @Override
    public StoreTravelOrder getByOderId(String orderId) {
        return travelOrderMapper.selectOne(new LambdaQueryWrapper<StoreTravelOrder>()
                .eq(StoreTravelOrder::getOrderId, orderId));
    }

    /**
     * 订单列表（旅游）
     * @param userId 用户uid
     * @param status 评价等级|0=未支付,1=待使用,2=已使用，待评价,3=已完成,-3=售后/退款
     * @param pageRequest 分页参数
     * @return 订单结果列表
     */
    @Override
    public Page<StoreTravelOrder> getUserOrderList(Integer userId, Integer status, PageParamRequest pageRequest) {
        Page<StoreTravelOrder> page = new Page<>(pageRequest.getPage(), pageRequest.getLimit(),true);

        LambdaQueryWrapper<StoreTravelOrder> lqw = new LambdaQueryWrapper<>();
        orderUtils.statusTravelApiByWhere(lqw, status);
        if(userId != null){
            lqw.eq(StoreTravelOrder::getUid, userId);
        }
        lqw.orderByDesc(StoreTravelOrder::getId);

        return travelOrderMapper.selectPage(page, lqw);
    }

    /**
     * 订单退款列表（旅游）
     * @param userId 用户uid
     * @param status 评价等级|0=未支付,1=待使用,2=已使用，待评价,3=已完成,-3=售后/退款
     * @param pageRequest 分页参数
     * @return 订单结果列表
     */
    @Override
    public Page<StoreTravelOrder> getUserOrderRefundList(Integer userId, Integer status, PageParamRequest pageRequest) {
        Page<StoreTravelOrder> page = new Page<>(pageRequest.getPage(), pageRequest.getLimit(),true);
        LambdaQueryWrapper<StoreTravelOrder> lqw = new LambdaQueryWrapper<>();
        orderUtils.statusTravelApiByWhere(lqw, status);
        lqw.orderByDesc(StoreTravelOrder::getId);
        return travelOrderMapper.selectPage(page, lqw);
    }

    /**
     * 根据orderId或者payId查询（旅游）
     * @param orderId 订单号或者支付单号
     * @param pageRequest 分页参数
     * @return 订单结果列表
     */
    @Override
    public Page<StoreTravelOrder> getUserOrderByOderId(String  orderId, PageParamRequest pageRequest) {
        Page<StoreTravelOrder> page = new Page<>(pageRequest.getPage(), pageRequest.getLimit(),true);
        LambdaQueryWrapper<StoreTravelOrder> lqw = new LambdaQueryWrapper<>();
        lqw.eq(StoreTravelOrder::getOrderId, orderId).or();
        lqw.eq(StoreTravelOrder::getPayId,orderId);
        return travelOrderMapper.selectPage(page, lqw);
    }

    /**
     * 根据orderId或者payId查询（旅游）订单退款列表（旅游）
     * @param orderId 订单号或者支付单号
     * @param pageRequest 分页参数
     * @return 订单结果列表
     */
    @Override
    public Page<StoreTravelOrder> getUserOrderRefundByOderId(String orderId, PageParamRequest pageRequest) {
        Page<StoreTravelOrder> page = new Page<>(pageRequest.getPage(), pageRequest.getLimit(),true);
        LambdaQueryWrapper<StoreTravelOrder> lqw = new LambdaQueryWrapper<>();
        lqw.eq(StoreTravelOrder::getOrderId, orderId).or();
        lqw.eq(StoreTravelOrder::getPayId,orderId);
        lqw.eq(StoreTravelOrder::getRefundStatus,1);
        return travelOrderMapper.selectPage(page, lqw);
    }

}
